/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.seari.ats_iscs.handler;

import com.seari.ats_iscs.AtsIscsHelper;
import com.seari.bean.ats_iscs.AtsIscsDataBean;
import com.seari.utils.DataUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @author Rainbow
 */
public class AtsIscsDecoder extends ByteToMessageDecoder {
    protected static Logger logger = LoggerFactory.getLogger(AtsIscsDecoder.class);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        //读取报文头，并判断
        if (in.readableBytes() < AtsIscsHelper.FRAME_LENGTH_WITHOUT_CONTENT) {
            //小于最小帧长直接返回
            logger.warn("frame minimum length Less than eight");
            return;
        }
        in.markReaderIndex();
        if (in.readByte() != (byte) 0x55 || in.readByte() != (byte) 0xAA || in.readByte() != (byte) 0x55 || in.readByte() != (byte) 0xAA) {
            //未读到正确的HEAD直接返回
            return;
        }
        byte[] messageLength = new byte[2];
        in.readBytes(messageLength);
        //长度为报文类型和报文参数的总长度
        int totalLength = DataUtil.getHighLowByteValue(messageLength[1], messageLength[0]);
        if (in.readableBytes() < totalLength) {
            //包长不够时重置读指针等待下次包数据
            in.resetReaderIndex();
            logger.debug("===AtsIscsDecoder.decode.包长不够时重置读指针等待下次包数据");
            return;
        }
        byte[] content = new byte[totalLength];
        in.readBytes(content);
        byte[] headInfo = ArrayUtils.addAll(AtsIscsHelper.ATS_ISCS_HEADER, messageLength);
        byte[] result = ArrayUtils.addAll(headInfo, content);
        AtsIscsDataBean dataBean = decode(headInfo, content);
        dataBean.setHexStr(DataUtil.BytesToHexStr(result));
        if (null == dataBean || "".equals(dataBean)) {
            logger.warn("parse frame failed");
        } else {
            out.add(dataBean);
        }

        logger.info(DataUtil.BytesToHexStr(result));
    }

    public AtsIscsDataBean decode(byte[] headInfo, byte[] content) {
        AtsIscsDataBean atsIscsDataBean = null;
        if (headInfo[0] == (byte) 0x55 && headInfo[1] == (byte) 0xAA && headInfo[2] == (byte) 0x55 && headInfo[3] == (byte) 0xAA) {
            atsIscsDataBean = new AtsIscsDataBean();
            Integer length = (headInfo[5] & 0xff) << 8 | headInfo[4] & 0xff;
            atsIscsDataBean.setMessageLength(length);
            Integer type = (content[1] & 0xff) << 8 | content[0] & 0xff;
            atsIscsDataBean.setMessageType(type);
            byte[] messageContent = new byte[content.length - 2];
            System.arraycopy(content, 2, messageContent, 0, messageContent.length);
            atsIscsDataBean.setContent(messageContent);
        } else {
            logger.warn("frame illegal");
        }
        return atsIscsDataBean;
    }

}
